/**
 * @author alteredq / http://alteredqualia.com/
 */

THREE.MaskPass = function ( scene, camera ) {

  THREE.Pass.call( this );

  this.scene = scene;
  this.camera = camera;

  this.clear = true;
  this.needsSwap = false;

  this.inverse = false;

};

THREE.MaskPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {

  constructor: THREE.MaskPass,

  render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {

    var context = renderer.context;
    var state = renderer.state;

    // don't update color or depth

    state.buffers.color.setMask( false );
    state.buffers.depth.setMask( false );

    // lock buffers

    state.buffers.color.setLocked( true );
    state.buffers.depth.setLocked( true );

    // set up stencil

    var writeValue, clearValue;

    if ( this.inverse ) {

      writeValue = 0;
      clearValue = 1;

    } else {

      writeValue = 1;
      clearValue = 0;

    }

    state.buffers.stencil.setTest( true );
    state.buffers.stencil.setOp( context.REPLACE, context.REPLACE, context.REPLACE );
    state.buffers.stencil.setFunc( context.ALWAYS, writeValue, 0xffffffff );
    state.buffers.stencil.setClear( clearValue );

    // draw into the stencil buffer

    renderer.render( this.scene, this.camera, readBuffer, this.clear );
    renderer.render( this.scene, this.camera, writeBuffer, this.clear );

    // unlock color and depth buffer for subsequent rendering

    state.buffers.color.setLocked( false );
    state.buffers.depth.setLocked( false );

    // only render where stencil is set to 1

    state.buffers.stencil.setFunc( context.EQUAL, 1, 0xffffffff );  // draw if == 1
    state.buffers.stencil.setOp( context.KEEP, context.KEEP, context.KEEP );

  }

} );


THREE.ClearMaskPass = function () {

  THREE.Pass.call( this );

  this.needsSwap = false;

};

THREE.ClearMaskPass.prototype = Object.create( THREE.Pass.prototype );

Object.assign( THREE.ClearMaskPass.prototype, {

  render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {

    renderer.state.buffers.stencil.setTest( false );

  }

} );